from datetime import datetime
from typing import Dict, List, Optional, Union

from pydantic import BaseModel, ValidationError


class RetrospectNode(BaseModel):
    workorder_code: str
    raw_workorder_code: str
    procedure_code: str = ""
    production_type: str
    produce_unit_code: str = ""
    process_section: str = ""
    device_code: str
    production_model: str
    material_info: str
    qr_code: str
    check_result: str = ""  # 默认值为空
    code_index: int = 0  # 默认值为 0
    op_type: str  # 默认值为 in
    material_type: str
    material_code: str
    code_type: str
    require_num: float
    ng_list: List = None  # 不合格品列表
    # op_time: datetime = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
    op_time: datetime


class MaterialConfig(BaseModel):
    material_code: str
    material_name: str
    material_quota: float
    material_type: str
    code_type: str
    is_check_miss_process: Optional[bool] = False
    material_spec: str


class BomInfo(BaseModel):
    product_in: List[MaterialConfig] = []
    product_out: List[MaterialConfig] = []


class WorkOrderConfig(BaseModel):
    workorder_code: str
    workorder_status: str
    workorder_type: str = ""  # 可能为空
    product_code: str
    production_type: str = ""  # 可能为空
    procedure_code: str = ""
    procedure_name: str = ""
    produce_unit_code: str = ""
    process_section: str = ""
    production_model: str = "normal"
    is_rework_workorder: bool = False
    bom_info: BomInfo
    device_code: str
    device_name: str


class RetrospectType:
    """追溯查询类型"""

    PRODUCT_IN = "in"  # 投入
    PRODUCT_OUT = "out"  # 产出

    @classmethod
    def all_types(cls):
        return [cls.PRODUCT_IN, cls.PRODUCT_OUT]


class CodeTypeEnum:
    """
    码值类型枚举
    """

    single_code = "single_code"
    batch_code = "batch_code"


class RetrospectNodeCheckResult:
    check_suc = ""
    check_fail = "不合格"


class RetrospectParams(BaseModel):
    qr_code: str
    op_type: str
    material_code: Optional[str] = None
    work_order_code: Optional[str] = None
    check_result: str = RetrospectNodeCheckResult.check_suc
    ng_list: List = None  # [{"code": "", "num": ""}]
    op_time: Optional[datetime] = None
    material_quota: Union[int, float, None] = None

    @classmethod
    def validate_items(cls, items: List[Dict]):
        """
        验证输入的 retrospect_items 列表是否合法
        :param items: 输入的待验证字典列表
        :raises ValueError: 当校验不通过时抛出异常
        """
        try:
            return [cls(**item) for item in items]
        except ValidationError as e:
            raise ValueError(f"retrospect_items 校验失败: {str(e)}")
